<!--
  图片上传组件，同一个页面使用多个该组件时需要确保uploadId值唯一

  用法：
    <qm-picture-upload :params="{type:'avatar',dataKey:'xxxId'}"></qm-picture-upload>
 -->
<template>
  <f7-list class="pic_upload">
    <f7-block-title v-if="showtitle" class="qm-title">上传证明</f7-block-title>
    <template v-if="!disabled">
      <span
        v-for="(file, index) in dbfiles"
        :key="file.attachmentId"
        :title="file.fileName"
        style="position: relative"
      >
        <div
          style="
            width: calc(155px * var(--ratio));
            height: calc(155px * var(--ratio));
            overflow: hidden;
            text-align: center;
            vertical-align: middle;
            border-radius: 8px;
          "
        >
          <img
            :src="downUrl + '?attachmentId=' + file.attachmentId"
            @click="openPhotoBrowser(index)"
          />
        </div>
        <f7-icon
          f7="multiply_circle_fill"
          class="delete"
          @click.native="removeDbFile(file)"
        ></f7-icon>
        <!-- <a
          class="col button button-fill color-gray"
          style="margin-top: -10px"
          @click="removeDbFile(file)"
          >删除</a
        > -->
        <div
          class="gauge demo-gauge"
          style="
            width: 70%;
            height: 70%;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            position: absolute;
          "
          @click="openPhotoBrowser(index)"
        >
          <!-- <svg width="70px" height="70px" viewBox="0 0 250 250" class="gauge-svg">
            <circle
              stroke="#eeeeee"
              stroke-width="10"
              fill="transparent"
              cx="125"
              cy="125"
              r="120"
              class="gauge-back-circle"
            ></circle>
            <circle
              transform="rotate(-90 125 125)"
              stroke="#2196f3"
              stroke-width="10"
              stroke-dasharray="753.9822368615503"
              stroke-dashoffset="0"
              fill="none"
              cx="125"
              cy="125"
              r="120"
              class="gauge-front-circle"
            ></circle>
            <text
              x="50%"
              y="50%"
              font-weight="500"
              font-size="80"
              fill="#2196f3"
              dy="0"
              text-anchor="middle"
              dominant-baseline="middle"
              class="gauge-value-text"
            >100%</text>
          </svg>-->
        </div>
      </span>
      <span
        v-for="(file, index) in files"
        :key="file.id"
        :title="file.name"
        v-show="file.active || file.success"
        style="position: relative"
      >
        <div
          style="
            width: calc(155px * var(--ratio));
            height: calc(155px * var(--ratio));
            overflow: hidden;
            text-align: center;
            vertical-align: middle;
            border-radius: 8px;
          "
        >
          <img
            v-if="file.thumb"
            :src="file.thumb"
            @click="openPhotoBrowser(dbfiles.length + index)"
          />
          <img
            v-if="!file.thumb"
            src="../../../assets/img/Default_picture.png"
          />
        </div>
        <f7-icon
          f7="multiply_circle_fill"
          class="delete"
          @click.native="removeFile(file)"
        ></f7-icon>
        <!-- <a
          v-if="file.success"
          class="col button button-fill color-gray"
          style="margin-top: -10px;"
          @click="removeFile(file)"
        >删除</a>
        <a
          v-if="file.error"
          class="col button button-fill color-gray"
          style="margin-top: -10px;"
          @click="removeFile(file)"
        >{{formatError(file)}}</a> -->
        <div
          class="gauge demo-gauge"
          style="
            width: 70%;
            height: 70%;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            position: absolute;
          "
          v-show="file.active"
        >
          <svg
            width="70px"
            height="70px"
            viewBox="0 0 250 250"
            class="gauge-svg"
          >
            <circle
              stroke="#eeeeee"
              stroke-width="10"
              fill="transparent"
              cx="125"
              cy="125"
              r="120"
              class="gauge-back-circle"
            />
            <circle
              transform="rotate(-90 125 125)"
              stroke="#2196f3"
              stroke-width="10"
              stroke-dasharray="753.9822368615503"
              :stroke-dashoffset="
                ((100 - file.progress) / 100) * 753.9822368615503
              "
              fill="none"
              cx="125"
              cy="125"
              r="120"
              class="gauge-front-circle"
            />
            <text
              x="50%"
              y="50%"
              font-weight="500"
              font-size="80"
              fill="#2196f3"
              dy="0"
              text-anchor="middle"
              dominant-baseline="middle"
              class="gauge-value-text"
            >
              {{ file.progress }}%
            </text>
          </svg>
        </div>
      </span>

      <file-upload
        class="addPic"
        :input-id="uploadId"
        :post-action="postUrl"
        :chunk-enabled="chunkEnabled"
        :chunk="{
          action: chunkUrl,
          minSize: chunkMinSize * 1048576,
          maxActive: chunkMaxActive,
          maxRetries: chunkMaxRetries,
          finishBody: params,
          handler: handlerClass,
        }"
        :extensions="extensions"
        :accept="accept"
        :multiple="multiple"
        :size="size"
        v-model="files"
        @input-filter="inputFilter"
        @input-file="inputFile"
        :ref="uploadId"
        :data="params"
        v-show="!isPlus"
      ></file-upload>
      <f7-link
        class="addPic"
        raised
        @click="$refs.actionsOneGroup.f7Actions.open()"
        v-show="isPlus"
      >
      </f7-link>
    </template>
    <template v-else>
      <span v-for="(file, index) in dbfiles" :key="file.attachmentId">
        <div
          style="
            width: 80px;
            height: 100px;
            text-align: center;
            display: table-cell;
            vertical-align: middle;
            border: 1px solid #b1afaf;
            border-radius: 5px;
          "
        >
          <img
            :src="downUrl + '?attachmentId=' + file.attachmentId"
            @click="openPhotoBrowser(index)"
          />
        </div>
      </span>
    </template>

    <f7-actions ref="actionsOneGroup">
      <f7-actions-group>
        <f7-actions-label>上传方式选择</f7-actions-label>
        <f7-actions-button @click="appendByGallery">手机相册</f7-actions-button>
        <f7-actions-button @click="appendByCamera">相机拍照</f7-actions-button>
        <f7-actions-button color="red">取消</f7-actions-button>
      </f7-actions-group>
    </f7-actions>
  </f7-list>
</template>
<script>
import _ from "lodash";
import ImageCompressor from "image-compressor.js";
import FileUpload from "vue-upload-component";
import formatter from "../../framework/formatter";
import Config from "../../config";
import ChunkUploadHandler from "../../polyfill/ChunkUploadHandler";
export default {
  components: {
    FileUpload,
  },
  props: {
    // 是否显示标题
    showtitle: {
      type: Boolean,
      default: true,
    },
    uploadId: {
      type: String,
      default: "file",
    },
    params: {
      type: Object,
      default: {},
    },
    extensions: {
      type: String,
    },
    accept: {
      type: String,
    },
    multiple: {
      type: Boolean,
      default: true,
    },
    size: {
      type: Number,
      default: 1024 * 1024 * 10,
    },
    chunkUrl: {
      type: String,
      default: "/api/base/chunkUpload/upload",
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    // 是否添加时间水印
    timeWatermark: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      actionsOneGroup: false,
      downUrl: "/api/base/fileupload/downFile",
      getUrl: "/api/base/fileupload/getFiles",
      deleteUrl: "/api/base/fileupload/delFile",
      postUrl: "/api/base/fileupload/uploadFile",
      files: [],
      dbfiles: [],
      chunkEnabled: true,
      // 1MB by default
      chunkMinSize: 1,
      chunkMaxActive: 3,
      chunkMaxRetries: 5,
      popupOpened: false,
      uploadAuto: true,
      handlerClass: ChunkUploadHandler,
      autoCompress: 2048,
    };
  },
  mounted() {
    if (window.plus) {
      this.postUrl = Config.api.upload;
      this.downUrl = Config.api.download;
      // this.deleteUrl = Config.api.deleteUrl;
    }
    // 打包时不需要
    // this.getUrl = Config.api.getUrl;
    // this.deleteUrl = Config.api.deleteUrl;
  },
  created() {
    // 打包时不需要
    // this.getUrl = Config.api.getUrl;
    this.$f7.request.post(this.getUrl, this.params, (r) => {
      r = JSON.parse(r);
      if (r && r.success) {
        this.dbfiles = r.parameters.files || [];
      } else {
        this.$framework.$f7.dialog.toast("获取文件失败");
      }
    });
  },
  methods: {
    getThumb(file) {
      if (file.thumb) {
        return file.thumb;
      } else if (file.name) {
        let extension = file.name.substring(file.name.lastIndexOf(".") + 1);
        if (
          extension &&
          "avi,doc,docx,jpg,mp4,pdf,png,ppt,pptx,rar,txt,xls,xlsx,zip"
            .split(",")
            .includes(extension.toLowerCase())
        ) {
          return "/static/img/file/" + extension.toLowerCase() + ".png";
        }
      }
      return "/static/img/file/default.png";
    },
    formatError(file) {
      var error = "上传失败";
      switch (file.error) {
        case "size":
          error =
            "上传失败：文件太大，不超过" + formatter.formatFileSize(this.size);
          break;
        case "extension":
          error = "上传失败：文件类型不符，只允许" + this.accept;
          break;
        case "timeout":
          error = "网络超时";
          break;
        case "abort":
          error = "用户放弃";
          break;
        case "network":
          error = "网络连接失败";
          break;
        case "server":
          error = "服务器错误";
          break;
        case "denied":
          error = "请求无效";
          break;
        default:
          error = "上传失败";
          break;
      }
      return error;
    },
    inputFilter(newFile, oldFile, prevent) {
      if (newFile && !oldFile) {
        // Before adding a file
        // 添加文件前
        // Filter system files or hide files
        // 过滤系统文件 和隐藏文件
        if (/(\/|^)(Thumbs\.db|desktop\.ini|\..+)$/.test(newFile.name)) {
          return prevent();
        }
        // Filter php html js file
        // 过滤 php html js 文件
        if (/\.(php5?|html?|jsx?)$/i.test(newFile.name)) {
          return prevent();
        }
        // Automatic compression
        // 自动压缩
        if (
          newFile.file &&
          newFile.type.substr(0, 6) === "image/" &&
          this.autoCompress &&
          this.autoCompress > 0 &&
          this.autoCompress < newFile.size
        ) {
          newFile.error = "compressing";
          const imageCompressor = new ImageCompressor(null, {
            convertSize: Infinity,
            maxWidth: 512,
            maxHeight: 512,
          });
          imageCompressor
            .compress(newFile.file)
            .then((file) => {
              console.log("压缩成功");
              this.$refs[this.uploadId].update(newFile, {
                error: "",
                file,
                size: file.size,
                type: file.type,
              });
            })
            .catch((err) => {
              this.$refs[this.uploadId].update(newFile, {
                error: err.message || "compress",
              });
            });
        }
      }
      if (newFile && (!oldFile || newFile.file !== oldFile.file)) {
        // Create a blob field
        // 创建 blob 字段
        newFile.blob = "";
        let URL = window.URL || window.webkitURL;
        if (URL && URL.createObjectURL) {
          newFile.blob = URL.createObjectURL(newFile.file);
        }
        // Thumbnails
        // 缩略图
        newFile.thumb = "";
        if (newFile.blob && newFile.type.substr(0, 6) === "image/") {
          newFile.thumb = newFile.blob;
        }
      }
    },
    // add, update, remove File Event
    inputFile(newFile, oldFile) {
      if (newFile && oldFile) {
        // update
        if (newFile.active && !oldFile.active) {
          // beforeSend
          // min size
          if (
            newFile.size >= 0 &&
            this.minSize > 0 &&
            newFile.size < this.minSize
          ) {
            this.$refs[this.uploadId].update(newFile, { error: "size" });
          }
        }
        if (newFile.progress !== oldFile.progress) {
          // progress
        }
        if (newFile.error && !oldFile.error) {
          this.$framework.$f7.dialog.toast(
            this.formatError(newFile) || "上传失败"
          );
        }
        if (newFile.success && !oldFile.success) {
          // success
          let rep = newFile.response;
          if (Object.keys(rep).includes("success") && rep.success) {
            // 上传成功
            this.$emit("success", newFile);
          } else {
            // 上传失败
            this.$f7.dialog.alert(
              newFile.response.message || "服务器不允许该文件上传"
            );
            this.files.pop();
          }
        }
      }
      if (!newFile && oldFile) {
        // remove
        if (oldFile.success && oldFile.response.id) {
          // $.ajax({
          //   type: 'DELETE',
          //   url: '/upload/delete?id=' + oldFile.response.id,
          // })
        }
      }
      // Automatically activate upload
      if (
        Boolean(newFile) !== Boolean(oldFile) ||
        oldFile.error !== newFile.error
      ) {
        if (this.uploadAuto && !this.$refs[this.uploadId].active) {
          this.$refs[this.uploadId].active = true;
        }
      }
    },
    appendByCamera() {
      window.plus.camera.getCamera().captureImage(
        (path) => {
          if (this.timeWatermark) {
            this.fnTimeWatermark(path);
          } else {
            this.appendToFiles(path);
          }
        },
        (e) => {
          if (e.code == 12 || e.code == 11) {
            this.$framework.$f7.dialog.toast("用户取消选择");
          } else {
            this.$framework.$f7.dialog.toast("添加文件失败：" + e.message);
          }
          console.log(e);
        }
      );
    },
    // 从相册添加文件
    appendByGallery() {
      window.plus.gallery.pick(
        (path) => {
          this.appendToFiles(path);
        },
        (e) => {
          if (e.code == 12 || e.code == 11) {
            this.$framework.$f7.dialog.toast("用户取消选择");
          } else {
            this.$framework.$f7.dialog.toast("添加文件失败：" + e.message);
          }
        }
      );
    },
    appendToFiles(path) {
      let that = this;
      window.plus.io.resolveLocalFileSystemURL(
        path,
        (entry) => {
          entry.file((file) => {
            var reader = new window.plus.io.FileReader();
            reader.onloadend = function (e) {
              var file = (function (path, name) {
                var arr = path.split(","),
                  mime = arr[0].match(/:(.*?);/)[1],
                  bstr = atob(arr[1]),
                  n = bstr.length,
                  u8arr = new Uint8Array(n);
                while (n--) {
                  u8arr[n] = bstr.charCodeAt(n);
                }
                  that.$refs[that.uploadId].add(file);
                return new File([u8arr], name, { type: mime });
              })(e.target.result, entry.name);
            };
            reader.readAsDataURL(file);
          });
        },
        (e) => {
          console.log(e);
        }
      );
    },
    // 添加时间水印
    fnTimeWatermark(path) {
      let _this = this,
        image = new Image(),
        canvas = document.createElement("canvas"),
        ctx = canvas.getContext("2d"),
        reader = new window.plus.io.FileReader();

      window.plus.io.resolveLocalFileSystemURL(
        path,
        (entry) => {
          entry.file((file) => {
            reader.onload = function () {
              image.src = reader.result;

              image.onload = function () {
                let w = image.naturalWidth,
                  h = image.naturalHeight;

                canvas.width = w;
                canvas.height = h;
                ctx.drawImage(image, 0, 0);
                ctx.font = "600 100px serif";
                ctx.textBaseline = "hanging";
                let date = formatter.formatDateTime(new Date());
                ctx.fillStyle = "#FFF";
                ctx.fillText(date, 20, 100);

                let arr = canvas.toDataURL("image/png").split(","),
                  mime = arr[0].match(/:(.*?);/)[1],
                  bstr = atob(arr[1]),
                  n = bstr.length,
                  u8arr = new Uint8Array(n);

                while (n--) {
                  u8arr[n] = bstr.charCodeAt(n);
                }

                _this.$refs[_this.uploadId].add(
                  new File([u8arr], file.name, { type: mime })
                );
              };
            };
            reader.readAsDataURL(file);
          });
        },
        (e) => {
          console.log(e);
        }
      );
    },
    removeDbFile(file) {
      let attachmentId = file.attachmentId;
      console.log(this.files);
      if (attachmentId != undefined) {
        this.$f7.dialog.confirm("该文件已上传成功，确定要删除嘛？", (r) => {
          if (r) {
            this.$f7.request.post(
              this.deleteUrl,
              { attachmentId: attachmentId },
              (r) => {
                console.log(r);
                r = JSON.parse(r);
                if (r && r.success) {
                  this.dbfiles.splice(this.dbfiles.indexOf(file), 1);
                  this.$framework.$f7.dialog.toast("文件删除成功");
                } else {
                  this.$framework.$f7.dialog.toast(r.message || "文件删除失败");
                }
              },
              (e) => {
                this.$framework.$f7.dialog.toast("文件删除失败");
              }
            );
          } else {
            this.dbfiles.splice(this.files.indexOf(file), 1);
          }
        });
      }
    },
    removeFile(file) {
      if (
        !file.response.parameters.file ||
        !file.response.parameters.file.key
      ) {
        this.$refs[this.uploadId].remove(file);
        return;
      }
      let attachmentId = file.response.parameters.file.key;
      if (file.success || attachmentId != undefined) {
        this.$f7.dialog.confirm("该文件已上传成功，确定要删除嘛？", (r) => {
          if (r) {
            this.$f7.request.post(
              this.deleteUrl,
              { attachmentId: attachmentId || file.chunk.sessionId },
              (r) => {
                r = JSON.parse(r);
                if (r && r.success) {
                  if (attachmentId == undefined) {
                    this.$refs[this.uploadId].remove(file);
                  } else {
                    this.files.splice(this.files.indexOf(file), 1);
                  }
                  this.$framework.$f7.dialog.toast("文件删除成功");
                } else {
                  this.$framework.$f7.dialog.toast(r.message || "文件删除失败");
                }
              },
              (e) => {
                this.$framework.$f7.dialog.toast("文件删除失败");
              }
            );
          }
        });
      } else {
        this.$refs[this.uploadId].remove(file);
      }
    },
    openPhotoBrowser(index) {
      let photos = [];
      this.dbfiles.forEach((f) => {
        photos.push({
          url: this.downUrl + "?attachmentId=" + f.attachmentId,
          caption: f.fileName,
        });
      });
      this.files.forEach((f) => {
        if (f.thumb) {
          photos.push({
            url: f.thumb,
            caption: f.name,
          });
        }
      });
      var photoBrowser = this.$f7.photoBrowser.create({
        photos: photos,
        type: "popup",
      });
      photoBrowser.open(index || 0);
      photoBrowser.on("closed", () => {
        photoBrowser.destroy();
      });
    },
  },
  computed: {
    isPlus() {
      return window.plus != undefined;
    },
  },
};
</script>
<style scoped>
.pic_upload {
  margin: 0px;
  margin-top: calc(32px * var(--ratio));
  --f7-block-title-text-color: #61677a;
  --f7-block-title-font-size: calc(28px * var(--ratio));
}
.qm-title {
  font-size: 15px;
  margin-left: 2px;
}
.chunk-loading {
  margin: -12px;
  display: flex;
  width: calc(100% + 24px);
}

.chunk-loading .chunk-loading-part {
  height: 25px;
  line-height: 25px;
  flex: 1;
  background: #ccc;
  font-size: 14px;
  color: white;
  text-align: center;
}

.chunk-loading .chunk-loading-part.chunk-loading-part__uploaded {
  background: #28a745;
}

.file-uploads {
  width: 80px;
}

.addPic {
  display: inline-block;
  width: calc(155px * var(--ratio));
  height: calc(155px * var(--ratio));
  border-radius: 8px;
  background: #e3e5e95e url(../../../assets/img/icon-plus.svg) no-repeat center;
  background-size: 100%;
  cursor: pointer;
}

.delete {
  position: absolute;
  right: 0;
  top: 0;
  transform: translate(35%, -35%);
  font-size: var(--font-size-maintitle);
  color: var(--color-text-subtext);
}
</style>
